package com.iam.api.controller;

import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.iam.api.service.SysUserService;
import com.iam.core.config.IamApplicationconfig;
import com.iam.core.config.IamAuthConfig;
import com.iam.core.config.Rsaconfig;
import com.iam.core.enums.SysLogType;
import com.iam.core.model.SysLog;
import com.iam.core.model.SysUser;
import com.iam.core.service.SysLogService;
import com.iam.core.utils.RsaUtil;
import jakarta.annotation.Resource;
import org.apache.tomcat.util.buf.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.rsa.crypto.RsaAlgorithm;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;
import java.util.List;

@RestController
@RequestMapping("sso")
public class SessionController {

    @Resource
    private SysUserService<SysUser> userService;

    @Autowired
    private IamAuthConfig iamAuthConfig;

    public static RsaUtil rsaUtil;

    @Autowired
    private SysLogService<SysLog> logService;

    @Autowired
    private SaTokenDao saTokenDao;

    static {
        rsaUtil = new RsaUtil();
        Rsaconfig rsaconfig = new Rsaconfig();
        rsaconfig.setAlgorithm(RsaAlgorithm.DEFAULT);
        rsaconfig.setPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvrvh/BoZ6bcnCltEWSyT9WnDOlfwXOHWotOS3j1rgE50UjQ82CFKArvVj5qpTT2AJAlDYz0EzTDNXKluyPcOzxL7qJSdASjJuR5ewrXJcL/6Q51465vQqijlkYrZx/kg57Oy5eVSJKZhTpNiwAM0iJ7Mjt7gzPU4nqQCkzb8ZLvl8O/+93hrMQu4zk+QWjeBz6rqWNPZA4prOedUUUQIlsUpClL8+HuF6lhc4GiyXKIuqFv7yfKECZfdfI8+e5Awxc57sRqyTOMtQD34P5t6anYQhyTuM5CVHW/Z8q7o0MDeJ941MxmxUxlCASFbZPAfqOMBNI5UjjKs5uiB0CIvXQIDAQAB");
        rsaconfig.setPrivateKey("MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC+u+H8GhnptycKW0RZLJP1acM6V/Bc4dai05LePWuATnRSNDzYIUoCu9WPmqlNPYAkCUNjPQTNMM1cqW7I9w7PEvuolJ0BKMm5Hl7Ctclwv/pDnXjrm9CqKOWRitnH+SDns7Ll5VIkpmFOk2LAAzSInsyO3uDM9TiepAKTNvxku+Xw7/73eGsxC7jOT5BaN4HPqupY09kDims551RRRAiWxSkKUvz4e4XqWFzgaLJcoi6oW/vJ8oQJl918jz57kDDFznuxGrJM4y1APfg/m3pqdhCHJO4zkJUdb9nyrujQwN4n3jUzGbFTGUIBIVtk8B+o4wE0jlSOMqzm6IHQIi9dAgMBAAECggEBAL6LdHgmmzyhfJ8cDmwH3MiPoDnpIHeqJoMEWvUq5vqHZi25gg9pMkcI35FXMUu45QsbNfcuPl2/I2ou2j5qkqDMlh0UWsWNufj2HjTm5xd8sshZyTOXth5IPQ/pZygf+n9/RnnlXuq+TPfyxfSNPy49dp5EitA3KxlRQEFR7VOzqJPSqAivL4tTcGZ6hCeHTT5u9WJXBENWm0VGuVpV1iIfHtQ1pio8k8XqPO29E5JzEbgv6tqI4E9jT1Nu2WlqvpwuG3BEG9A/O2mZPEENDaCwiiTY+PlqFd7RD2d4aSXgLJoqJc86MaJmR7Q2CIujb1m8z6vqvNp5U6+nKnfVOQECgYEA7bcBCGwrClMbhgU65gKWZKVRyThhdBxWCeA+dHvUOeR5BY+1P6Rw3i7BvVSqOvNCx+AiHKoCZVVvhA1EBXNX2qaCzL0y3AZROKeOVfqlCIcSHmlQCYk9tCsguW5FW46IsQjrqo5COnpP3ffSD9lDN48FmEHowY/QGwVCa0fd6HcCgYEAzWe/Lr4C1gC16HyWoDMMgz4h3369kRflrxE0xC12n+6l+PypxfZQey31NFj3xG0ZsS+SEiI89xH8L64cwJHWlahBNLb5DoBFVcgm2jiqEB00O1rBAd89DDQ4rK7sXVf0Sau+/chAUDKH6ZAzR8kQRfQn0iQ3jrga0cik/CKrL8sCgYBbM7M5wAZjV69fo/IM/UEmLCdMxEzfd1+rOlW76yZpb7be41vupvCGzfmW4jzNkTc16FAuHyv8JOM8DrriPHagdPIKCyzQLbxLuD1rz1YyB2B0OoNypSz/SuyrOBt0HSNkiL+iGCJgvTyXNNVrLzgSwNSsrdzXJo35T/NDpbcF0QKBgHT5YizyVJcerHmLihQNPlD3bz7h5H7ehxTdzZjy8x09QRO8f8qW7VpY381B5UfdgcYf+yWMjf9+JInas9EOvI9Z1Fh64vbZIaMqasXXgzHOD9LFaijwwslSa/wbWcwGrL3PquLHyahiPnhKgIme/T95Pbw0l9cVDWDuzNYxwB9lAoGAYF4TSeEjbnQKoo5/H3bsTOdr0c27KIyBKrpNfXosy01l2f5kLdFmDDGvIgvVXtN3Tt3Jsi+NWb6zaPgEWGpbGqVvtPnDZVpnTB8kV/fTw5puUbg6JgRn2jUix2yyRj5hcceuv6kvmz0SNElmWxucbIUD3fcoItrWBjD2BM5z3qI=");
        rsaUtil.setRsAconfig(rsaconfig);
    }

    @PostMapping("doLogin")
    public SaResult doLogin(String name, String pwd) {
        // 此处仅作模拟示例，真实项目需要从数据库中查询数据进行比对
        SysUser userInfo = userService.getOne(new QueryWrapper<SysUser>().eq("login_name", name));
        if (ObjectUtils.isEmpty(userInfo)) {
            // 混淆数据，找不到用户和密码不匹配使用相同的返回内容
            return SaResult.error("登录失败：请检查用户名密码");
        }
        SysUser sysUser = new SysUser();
        sysUser.setUserId(userInfo.getUserId());
        // 30分钟内错误次数达到上限后不允许登录
        if (userInfo.getLoginFailNum() > iamAuthConfig.getMaxFailNum()) {
            if (!ObjectUtils.isEmpty(userInfo.getLoginDate())) {
                if ((System.currentTimeMillis() - userInfo.getLoginDate().getTime()) < IamApplicationconfig.LOGIN_LOCK_TIME) {
                    return SaResult.error("登陆失败次数已经累计达到" + iamAuthConfig.getMaxFailNum() + "次以上,请30分钟后再次尝试");
                }
            } else {
                sysUser.setLoginDate(new Date());
                userService.updateById(sysUser);
                return SaResult.error("登陆失败次数已经累计达到" + iamAuthConfig.getMaxFailNum() + "次以上,请30分钟后再次尝试");
            }
        }
        try {
            if (!ObjectUtils.isEmpty(userInfo) && userInfo.getLoginName().equals(name)
                    && rsaUtil.verify(userInfo.getPassword(), pwd)
            ) {
                StpUtil.login(userInfo.getUserId());
                List<String> roles = StpUtil.getRoleList();
                List<String> perms = StpUtil.getPermissionList();
                saTokenDao.set("x-token:login:permission:" + StpUtil.getTokenValue(), StringUtils.join(perms, ','), StpUtil.getTokenTimeout());
                saTokenDao.set("x-token:login:role:" + StpUtil.getTokenValue(), StringUtils.join(roles, ','), StpUtil.getTokenTimeout());
                // 登录成功后回滚错误次数
                sysUser.setLoginFailNum(0);
                userService.updateById(sysUser);
                SysUser user = userService.getById(userInfo.getUserId());
                user.setPassword(null);
                SaResult data = SaResult.data(StpUtil.getTokenInfo());
                data.setMsg("操作成功");

                logService.save(new SysLog(SysLogType.AUTH.getValue(), user.getUserName() + "登录成功"));
                return data;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        sysUser.setLoginFailNum(ObjectUtils.isEmpty(userInfo.getLoginFailNum()) ? 0 : userInfo.getLoginFailNum() + 1);
        userService.updateById(sysUser);
        return SaResult.error("登录失败：请检查用户名密码");
    }

}
